home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1995 April / Internet Tools.iso / applic / ncsa / Mac / Telnet2.6 / prerelease / d4 / Telnet2.6.1d4.src.sit.hqx / Telnet 2.6.1d4 source / source / tek / vgtek.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-11-22  |  34.3 KB  |  1,550 lines

  1. /*
  2.  *    vgtek.c by Aaron Contorer 1987 for NCSA
  3.  *    bugfixes by Tim Krauskopf 1988 for NCSA
  4.  *    TEK4105 support by Dave Whittington 1990 (for NCSA, of course)
  5.  *
  6.  *    Takes Tektronix codes as input; sends output to real graphics devices.
  7.  *
  8.  *    CHANGES TO MAKE:
  9.  *    create a function to make sure a window is attached to a real window.
  10.  *      Calling program will call this whenever switching between active windows.
  11.  *    Pass virtual window number to RG driver so it can call back.
  12.  */
  13.  
  14. #ifdef MPW
  15. #pragma segment TEKMAIN
  16. #endif
  17.  
  18. #include <Stdio.h>
  19. #include <Stdlib.h>
  20. #include "TelnetHeader.h"
  21. #include "event.proto.h"
  22. #include "maclook.proto.h"
  23. #include "wind.h"
  24.  
  25. #include "vsdata.h"
  26. #include "vsinterf.proto.h"
  27.  
  28. #include "vgfont.h"
  29. #include "vgtek.proto.h"
  30. #include "rg0.proto.h"
  31. #include "rgmp.proto.h"
  32. #include "tekrgmac.proto.h"
  33. #include "tekdefs.h"    /* NCSA: sb - all defines are now here, for easy access */
  34. #include "tekstor.proto.h"
  35.  
  36. static RGLINK RG[TEK_DEVICE_MAX] = {
  37.     RGMnewwin,        RGMdevname,        RGMinit,        RGMgin,
  38.     RGMpencolor,    RGMclrscr,        RGMclose,        RGMpoint,
  39.     RGMdrawline,    RGMinfo,        RGMpagedone,    RGMdataline,
  40.     RGMcharmode,    RGMgmode,        RGMtmode,        RGMshowcur,
  41.     RGMlockcur,        RGMhidecur,        RGMbell,        RGMuncover,
  42.  
  43.     RGMPnewwin,        RGMPdevname,    RGMPinit,        RG0returnshort,
  44.     RGMPpencolor,    RG0returnshort,    RGMPclose,        RGMPpoint,
  45.     RGMPdrawline,    RGMPinfo,        RG0oneshort,    RGMPdataline,
  46.     RGMPcharmode,    RG0void,        RG0void,        RG0void,
  47.     RG0void,        RG0void,        RG0oneshort,    RG0oneshort
  48. };
  49.  
  50. extern WindRec *screens;
  51.  
  52. static fontnum(short vw, short n);
  53. static storexy(short vw, short x, short y);
  54. static joinup(short hi, short lo, short e);
  55. static newcoord(short vw);
  56. static linefeed(short vw);
  57. static clipvec(short vw, short xa, short ya, short xb, short yb);
  58. static    short    VGcheck(short dnum);
  59.  
  60. static struct VGWINTYPE *VGwin[MAXVG];  /* BYU - virtual window descriptors */
  61.  
  62. static char state[MAXVG],savstate[MAXVG];
  63.     /* save state in a parallel array for speed */
  64. static TEKSTOREP VGstore[MAXVG]; /* the store where data for this window is kept */
  65. static char storing[MAXVG]; /* are we currently saving data from this window */
  66. static short drawing[MAXVG]; /* redrawing or not? */
  67.  
  68. static short charxset[NUMSIZES] = {56,51,34,31,112,168};
  69. static short charyset[NUMSIZES] = {88,82,53,48,176,264};
  70.  
  71. /*******************************************************************/
  72.  
  73. void    TEKMAINunload(void) {}
  74.  
  75. short donothing(void)    /* BYU LSC */
  76. {
  77.     return 0;
  78. }
  79.  
  80. /*
  81.  *    Set font for window 'vw' to size 'n'.
  82.  *    Sizes are 0..3 in Tek 4014 standard.
  83.  *    Sizes 4 & 5 are used internally for Tek 4105 emulation.
  84.  */
  85. static fontnum(short vw, short n)
  86. {
  87.     if ((n < 0) || (n >= NUMSIZES)) return(-1);
  88.     VGwin[vw]->fontnum = n;
  89.     VGwin[vw]->charx = charxset[n];
  90.     VGwin[vw]->chary = charyset[n];
  91.     return(0);
  92. }
  93.  
  94.  
  95. static storexy(short vw, short x, short y)
  96. /* set graphics x and y position */
  97. {
  98.     VGwin[vw]->curx = x;
  99.     VGwin[vw]->cury = y;
  100. }
  101.  
  102.  
  103. static joinup(short hi, short lo, short e)
  104. /* returns the number represented by the 3 pieces */
  105. {
  106. #if 1
  107.     return (((hi & 31) << 7) | ((lo & 31) << 2) | (e & 3));
  108. #else
  109.     return (((hi /* & 31 */ ) << 7) | ((lo /* & 31 */ ) << 2) | (e /* & 3 */));
  110. #endif
  111. } /* end joinup() */
  112.  
  113.  
  114. static newcoord(short vw)
  115. /*
  116.  *    Replace x,y with nx,ny
  117.  */
  118. {
  119.     VGwin[vw]->hiy = VGwin[vw]->nhiy;
  120.     VGwin[vw]->hix = VGwin[vw]->nhix;
  121.     VGwin[vw]->loy = VGwin[vw]->nloy;
  122.     VGwin[vw]->lox = VGwin[vw]->nlox;
  123.     VGwin[vw]->ey  = VGwin[vw]->ney;
  124.     VGwin[vw]->ex  = VGwin[vw]->nex;
  125.  
  126.     VGwin[vw]->curx = joinup(VGwin[vw]->nhix,VGwin[vw]->nlox,VGwin[vw]->nex);
  127.     VGwin[vw]->cury = joinup(VGwin[vw]->nhiy,VGwin[vw]->nloy,VGwin[vw]->ney);
  128. }
  129.  
  130.  
  131. static linefeed(short vw) 
  132. /* 
  133.  *    Perform a linefeed & cr (CHARTALL units) in specified window.
  134.  */
  135. {
  136. /*    short y = joinup(VGwin[vw]->hiy,VGwin[vw]->loy,VGwin[vw]->ey);*/
  137.     short y = VGwin[vw]->cury;
  138.     short x;
  139.  
  140.     if (y > VGwin[vw]->chary) y -= VGwin[vw]->chary;
  141.     else
  142.     {
  143.         y = 3119 - VGwin[vw]->chary;
  144.         VGwin[vw]->textcol = 2048 - VGwin[vw]->textcol;
  145.     }
  146.     x = VGwin[vw]->textcol;
  147.     storexy(vw,x,y);
  148. }
  149.  
  150. /*
  151.  *    Draw a vector in vw's window from x0,y0 to x1,y1.
  152.  *    Zoom the vector to the current visible window,
  153.  *    and clip it before drawing it.
  154.  *    Uses Liang-Barsky algorithm from ACM Transactions on Graphics,
  155.  *        Vol. 3, No. 1, January 1984, p. 7.
  156.  *
  157.  *  Note: since QuickDraw on the Mac already handles clipping, we
  158.  *          will not do any processing here.
  159.  *  14may91dsw
  160.  *
  161.  */
  162. static clipvec(short vw, short xa, short ya, short xb, short yb)
  163. {
  164.     short    t,b,l,r;
  165.     struct VGWINTYPE *vp;
  166.     long    hscale, vscale;
  167.     
  168.     vp = VGwin[vw];        /* BYU mod */
  169.  
  170.     hscale = INXMAX / (long) vp->winwide;
  171.     vscale = INYMAX / (long) vp->wintall;
  172.     
  173.     t = vp->wintop;
  174.     b = vp->winbot;
  175.     l = vp->winleft;
  176.     r = vp->winright;
  177.  
  178.     (*RG[vp->RGdevice].drawline) (vp->RGnum,
  179.         (short) ((long)(xa - l) * INXMAX / (long) vp->winwide),
  180.         (short) ((long)(ya- b) * INYMAX / (long) vp->wintall),
  181.         (short) ((long)(xb - l) * INXMAX / (long) vp->winwide),
  182.         (short) ((long)(yb- b) * INYMAX / (long) vp->wintall)
  183.         );
  184. } /* end clipvec() */
  185.  
  186.  
  187. /*
  188.  *    Draw a stroked character at the current cursor location.
  189.  *    Uses simple 8-directional moving, 8-directional drawing.
  190.  *
  191.  *    Modified 17jul90dsw: TEK4105 character set added.
  192.  */
  193. short    drawc(short vw, short c) /* character to draw */
  194. {
  195.     short        x,y,savex,savey;
  196.     short        strokex,strokey;
  197.     short        n;                        /* number of times to perform command */
  198.     char    *pstroke;                /* pointer into stroke data */
  199.     short        hmag,vmag;
  200.     short        xdir,ydir;
  201.     short        height;
  202.  
  203.     xdir = 1;
  204.     ydir = 0;
  205.  
  206.     if (c == 10)
  207.     {
  208.         linefeed(vw);
  209.         return(0);
  210.     }
  211.  
  212.     if (c == 7)
  213.     {
  214.         (*RG[VGwin[vw]->RGdevice].bell) (VGwin[vw]->RGnum);
  215.         TEKunstore(VGstore[vw]);
  216.         return(0);
  217.     }
  218.  
  219.     savey = y = VGwin[vw]->cury;
  220.     savex = x = VGwin[vw]->curx;
  221.  
  222.     if (c == 8)
  223.     {
  224.         if (savex <= VGwin[vw]->textcol) return(0);
  225.         savex -= VGwin[vw]->charx;
  226.         if (savex < VGwin[vw]->textcol) savex = VGwin[vw]->textcol;
  227.         VGwin[vw]->cury = savey;
  228.         VGwin[vw]->curx = savex;
  229.         return(0);
  230.     }
  231.  
  232.     if (VGwin[vw]->TEKtype)
  233.     {
  234.         height = VGwin[vw]->TEKSize;
  235.         if (c > 126)
  236.         {
  237.             height = 1;
  238.             (*RG[VGwin[vw]->RGdevice].pencolor)(VGwin[vw]->RGnum,VGwin[vw]->pencolor);
  239.         }
  240.         else
  241.             (*RG[VGwin[vw]->RGdevice].pencolor)(VGwin[vw]->RGnum,VGwin[vw]->TEKIndex);
  242.         hmag = (height*8);
  243.         vmag = (height*8);
  244.         
  245.         xdir = 0;
  246.         switch(VGwin[vw]->TEKRot)
  247.         {
  248.             case 0:
  249.                 xdir = 1;
  250.                 break;
  251.             case 90:
  252.                 ydir = 1;
  253.                 break;
  254.             case 180:
  255.                 xdir = -1;
  256.                 break;
  257.             case 270:
  258.                 ydir = -1;
  259.                 break;
  260.         }
  261.     }
  262.     else
  263.     {
  264.         hmag = VGwin[vw]->charx / 10;
  265.         vmag = VGwin[vw]->chary / 10;
  266.     }
  267.  
  268.     if ((c < 32) || (c > 137))
  269.         return(0);                    // Is this return value correct?
  270.     c -= 32;
  271.     pstroke = (VGwin[vw]->TEKtype) ? VGTEKfont[c] : VGfont[c];
  272.     while (*pstroke)
  273.     {
  274.         strokex = x;
  275.         strokey = y;
  276.         n = (*(pstroke++) - 48);    /* run length */
  277.         c = *(pstroke++);            /* direction code */
  278.  
  279.         switch(c)     /* horizontal movement: positive = right */
  280.         {
  281.         case 'e': case 'd': case 'c': case 'y': case 'h': case 'n':
  282.             x += (n * hmag) * xdir;
  283.             y += (n * hmag) * ydir;
  284.             break;
  285.         case 'q': case 'a': case 'z': case 'r': case 'f': case 'v':
  286.             x -= (n * hmag) * xdir;
  287.             y -= (n * hmag) * ydir;
  288.         }
  289.  
  290.         switch(c)    /* vertical movement: positive = up */
  291.         {
  292.         case 'q': case 'w': case 'e': case 'r': case 't': case 'y':
  293.             x -= (n * vmag) * ydir;
  294.             y += (n * vmag) * xdir;
  295.             break;
  296.         case 'z': case 'x': case 'c': case 'v': case 'b': case 'n':
  297.             x += (n * vmag) * ydir;
  298.             y -= (n * vmag) * xdir;
  299.         }
  300.  
  301.         switch(c)    /* draw or move */
  302.         {
  303.         case 'r': case 't': case 'y': case 'f': case 'h':
  304.         case 'v': case 'b': case 'n':
  305.             clipvec (vw,strokex,strokey,x,y);
  306.             break;
  307.         }
  308.     
  309.     } /* end while not at end of string */
  310.  
  311.     /* Update cursor location to next char position */
  312.     savex += VGwin[vw]->charx * xdir;
  313.     savey += VGwin[vw]->charx * ydir;
  314.     if ((savex < 0) || (savex > 4095) || (savey < 0) || (savey > 3119))
  315.     {
  316.         savex = savex < 0 ? 0 : savex > 4095 ? 4095 : savex;
  317.         savey = savey < 0 ? 0 : savey > 3119 ? 3119 : savey;
  318.     }
  319.  
  320.     if (VGwin[vw]->TEKtype)
  321.         (*RG[VGwin[vw]->RGdevice].pencolor)(VGwin[vw]->RGnum,VGwin[vw]->pencolor);
  322.  
  323.     VGwin[vw]->cury = savey;
  324.     VGwin[vw]->curx = savex;
  325. }
  326.  
  327. /***********************************************************
  328. ************************************************************
  329. ***                                                         ***
  330. **    All routines given below may be called by the user      **
  331. **    program.  No routines given above may be called from  **
  332. **    the user program.                                      **
  333. ***                                                         ***
  334. ************************************************************
  335. ***********************************************************/
  336.  
  337. /*    Initialize the whole VG environment.  Should be called ONCE
  338.  *    at program startup before using the VG routines.
  339.  */
  340. void    VGinit(void)
  341. {
  342.     short i;
  343.  
  344.     for (i = 0; i < MAXVG; i++) {
  345.         VGwin[i] = nil;
  346.         }
  347.  
  348.     for (i=0; i<TEK_DEVICE_MAX; i++) (*RG[i].init)();        /* BYU LSC */
  349. }
  350.  
  351. short VGgetVS(short theVGnum)                /* NCSA 2.5: give us the VS */
  352. {                                            /* NCSA 2.5 */
  353.     if (VGcheck(theVGnum)) {
  354.         return -1;
  355.         }
  356.         
  357.     return VGwin[theVGnum]->theVS;            /* NCSA 2.5 */
  358. }                                            /* NCSA 2.5 */
  359.  
  360. static    short    VGcheck(short dnum)
  361. {
  362.     if ((dnum >= MAXVG) || (dnum < 0)) return -1;
  363.  
  364.     if (VGwin[dnum] == nil) return -1;
  365.  
  366.     return 0;
  367. }
  368.  
  369. /*
  370.  *    create a new VG window and return its number.
  371.  *    New window will be attached to specified real device.
  372.  *    Returns -1 if unable to create a new VG window.
  373.  *
  374.  *    Modified 16jul90dsw: Support selection of 4105 or 4014.
  375.  */
  376. short VGnewwin
  377.   (
  378.     short device, /* number of RG device to use */
  379.     short theVS
  380.   )
  381. {
  382.     short    vw = 0;
  383.     short    theScrn;
  384.  
  385.     while ((vw < MAXVG) && (VGwin[vw] != nil)) vw++;
  386.     if (vw == MAXVG)
  387.         return(-1);
  388.         
  389.     VGwin[vw] = (struct VGWINTYPE *) NewPtrClear(sizeof(struct VGWINTYPE));
  390.     if (VGwin[vw] == nil) {
  391.         return -1;
  392.         }
  393.             
  394.     VGstore[vw] = newTEKstore();
  395.     if (VGstore[vw] == nil) {
  396.         DisposePtr((Ptr)VGwin[vw]);
  397.         VGwin[vw] = nil;
  398.         return -1;
  399.         }
  400.     
  401.     VGwin[vw]->id = 'VGWN';
  402.     VGwin[vw]->RGdevice = device;
  403.     VGwin[vw]->RGnum = (*RG[device].newwin)();
  404.  
  405.     theScrn = findbyVS(theVS);
  406.     VGwin[vw]->TEKtype = screens[theScrn].tektype;    // 0 = 4014, 1 = 4105
  407.  
  408.     if (VGwin[vw]->RGnum < 0)
  409.     {
  410.         /* no windows available on device */
  411.         DisposePtr((Ptr)VGwin[vw]);
  412.         VGwin[vw] = nil;
  413.         freeTEKstore(VGstore[vw]);
  414.         return(-1);
  415.     }
  416.             
  417.     VGwin[vw]->mode = ALPHA;
  418.     VGwin[vw]->TEKPanel = (pointlist) NULL;
  419.     VGwin[vw]->theVS = theVS;
  420.     state[vw] = DONE;
  421.     storing[vw] = TRUE;
  422.     VGwin[vw]->textcol = 0;
  423.     drawing[vw] = 1;
  424.     fontnum(vw,0);
  425.     (*RG[device].pencolor)(VGwin[vw]->RGnum,1);
  426.  
  427.     storexy(vw,0,3071);
  428. #if 1                                        /* BYU LSC */
  429.     VGzoom(vw,0,0,4095,3119);                /* BYU LSC - important */
  430. #else                                        /* BYU LSC */
  431.     VGzoom(vw,0,0,INXMAX-1,INYMAX-1);
  432. #endif                                        /* BYU LSC */
  433.     return(vw);
  434. }
  435.  
  436. /*    Release its real graphics device and its store. */
  437. void    VGclose(short vw)
  438. {
  439.     if (VGcheck(vw)) {
  440.         return;
  441.         }
  442.  
  443.     (*RG[VGwin[vw]->RGdevice].close)(VGwin[vw]->RGnum);
  444.     freeTEKstore(VGstore[vw]);
  445.     DisposePtr((Ptr)VGwin[vw]);
  446.     VGwin[vw] = nil;
  447. }
  448.  
  449. /*    Detach window from its current device and attach it to the
  450.  *    specified device.  Returns negative number if unable to do so.
  451.  *    Sample application:  switching an image from #9 to Hercules.
  452.  *    Must redraw after calling this.
  453.  */
  454. short    VGdevice(short vw, short dev)
  455. {
  456.     short newwin;
  457.  
  458.     if (VGcheck(vw)) {
  459.         return -1;
  460.         }
  461.  
  462.     newwin = (*RG[dev].newwin)();
  463.     if (newwin<0) return(newwin);    /* unable to open new window */
  464.  
  465.     (*RG[VGwin[vw]->RGdevice].close)(VGwin[vw]->RGnum);
  466.     VGwin[vw]->RGdevice = dev;
  467.     VGwin[vw]->RGnum = newwin;
  468.     VGwin[vw]->pencolor = 1;
  469.     VGwin[vw]->TEKBackground = 0;
  470.     fontnum(vw,1);
  471.     return(0);
  472. }
  473.  
  474. /*    Clear the store associated with window vw.  
  475.  *    All contents are lost.
  476.  *    User program can call this whenever desired.
  477.  *    Automatically called after receipt of Tek page command. */
  478. void    VGclrstor(short vw)
  479. {
  480.     if (VGcheck(vw)) {
  481.         return;
  482.         }
  483.  
  484.     freeTEKstore(VGstore[vw]);
  485.     VGstore[vw] = newTEKstore();
  486.         /* Don't have to check for errors --    */
  487.         /* there was definitely enough memory.    */
  488. }
  489.  
  490. /*    Successively call the function pointed to by 'func' for each
  491.  *    character stored from window vw.  Each character will
  492.  *    be passed in integer form as the only parameter.  A value of -1
  493.  *    will be passed on the last call to indicate the end of the data.
  494.  */
  495. void    VGdumpstore(short vw, short (*func )(short))
  496. {
  497.     short        data;
  498.     TEKSTOREP    st;
  499.  
  500.     if (VGcheck(vw)) {
  501.         return;
  502.         }
  503.  
  504.     st = VGstore[vw];
  505.     topTEKstore(st);
  506.     while ((data = nextTEKitem(st)) != -1) (*func)(data);
  507.     (*func)(-1);
  508. }
  509.  
  510. /*    This is the main Tek emulator process.  Pass it the window and
  511.  *    the latest input character, and it will take care of the rest.
  512.  *    Calls RG functions as well as local zoom and character drawing
  513.  *    functions.
  514.  *
  515.  *    Modified 16jul90dsw:
  516.  *        Added 4105 support.
  517.  */
  518. void VGdraw(short vw, char c)            /* the latest input char */
  519. {
  520.     char        cmd;
  521.     char        value;
  522.     char        goagain;    /* true means go thru the function a second time */
  523.     char        temp[80];
  524.     RgnHandle    PanelRgn;
  525.     struct    VGWINTYPE *vp;
  526.     pointlist    temppoint;
  527.  
  528.     if (VGcheck(vw)) {
  529.         return;
  530.         }
  531.  
  532.     vp = VGwin[vw];        /* BYU */
  533.  
  534.     temp[0] = c;
  535.     temp[1] = (char) 0;
  536.  
  537.     /*** MAIN LOOP ***/
  538.      do
  539.     {
  540.         c &= 0x7f;                /* BYU 2.4.15 */
  541.          cmd = (c >> 5) & 0x03;
  542.         value = c & 0x1f;
  543.         goagain = FALSE;
  544.  
  545.         switch(state[vw])
  546.         {
  547.         case HIY: /* beginning of a vector */
  548.             vp->nhiy = vp->hiy;
  549.             vp->nhix = vp->hix;
  550.             vp->nloy = vp->loy;
  551.             vp->nlox = vp->lox;
  552.             vp->ney  = vp->ey;
  553.             vp->nex  = vp->ex;
  554.             
  555.             switch(cmd)
  556.             {
  557.             case 0:
  558.                 if (value == 27)        /* escape sequence */
  559.                 {
  560.                     state[vw] = ESCOUT;
  561.                     savstate[vw] = HIY;
  562.                 }
  563.                 else if (value < 27)    /* ignore */
  564.                 {
  565.                     break;
  566.                 }
  567.                 else
  568.                 {
  569.                     state[vw] = CANCEL;
  570.                     goagain = TRUE;
  571.                 }
  572.                 break;
  573.             case 1:                        /* hiy */
  574.                 vp->nhiy = value;
  575.                 state[vw] = EXTRA;
  576.                 break;
  577.             case 2:                        /* lox */
  578.                 vp->nlox = value;
  579.                 state[vw] = DONE;
  580.                 break;
  581.             case 3:                        /* extra or loy */
  582.                 vp->nloy = value;
  583.                 state[vw] = LOY;
  584.                 break;
  585.             }
  586.             break;        
  587.         case ESCOUT:
  588.             if ((value != 13) && (value != 10) && (value != 27) && (value != '~'))
  589.             {
  590.                 state[vw] = savstate[vw];        /* skip all EOL-type characters */
  591.                 goagain = TRUE;
  592.             }
  593.             break;
  594.         case EXTRA:    /* got hiy; expecting extra or loy */
  595.             switch(cmd)
  596.             {
  597.             case 0:
  598.                 if (value == 27)        /* escape sequence */
  599.                 {
  600.                     state[vw] = ESCOUT;
  601.                     savstate[vw] = EXTRA;
  602.                 }
  603.                 else if (value < 27)    /* ignore */
  604.                 {
  605.                     break;
  606.                 }
  607.                 else
  608.                 {
  609.                     state[vw] = DONE;
  610.                     goagain = TRUE;
  611.                 }
  612.                 break;
  613.             case 1:                        /* hix */
  614.                 vp->nhix = value;
  615.                 state[vw] = LOX;
  616.                 break;
  617.             case 2:                        /* lox */
  618.                 vp->nlox = value;
  619.                 state[vw] = DONE;
  620.                 break;
  621.             case 3:                        /* extra or loy */
  622.                 vp->nloy = value;
  623.                 state[vw] = LOY;
  624.                 break;
  625.             }
  626.             break;
  627.         case LOY: /* got extra or loy; next may be loy or something else */
  628.             switch(cmd)
  629.             {
  630.             case 0:
  631.                 if (value == 27)        /* escape sequence */
  632.                 {
  633.                     state[vw] = ESCOUT;
  634.                     savstate[vw] = LOY;
  635.                 }
  636.                 else if (value < 27)    /* ignore */
  637.                 {
  638.                     break;
  639.                 }
  640.                 else
  641.                 {
  642.                     state[vw] = DONE;
  643.                     goagain = TRUE;
  644.                 }
  645.                 break;
  646.             case 1: /* hix */
  647.                 vp->nhix = value;
  648.                 state[vw] = LOX;
  649.                 break;
  650.             case 2: /* lox */
  651.                 vp->nlox = value;
  652.                 state[vw] = DONE;
  653.                 break;
  654.             case 3: /* this is loy; previous loy was really extra */
  655.                 vp->ney = (vp->nloy >> 2) & 3;
  656.                 vp->nex = vp->nloy & 3;
  657.                 vp->nloy = value;
  658.                 state[vw] = HIX;
  659.                 break;
  660.             }
  661.             break;
  662.         case HIX:                        /* hix or lox */
  663.             switch(cmd)
  664.             {
  665.             case 0:
  666.                 if (value == 27)        /* escape sequence */
  667.                 {
  668.                     state[vw] = ESCOUT;
  669.                     savstate[vw] = HIX;
  670.                 }
  671.                 else if (value < 27)    /* ignore */
  672.                 {
  673.                     break;
  674.                 }
  675.                 else
  676.                 {
  677.                     state[vw] = DONE;
  678.                     goagain = TRUE;
  679.                 }
  680.                 break;
  681.             case 1:                        /* hix */
  682.                 vp->nhix = value;
  683.                 state[vw] = LOX;
  684.                 break;
  685.             case 2:                        /* lox */
  686.                 vp->nlox = value;
  687.                 state[vw] = DONE;
  688.                 break;
  689.             }
  690.              break;
  691.     
  692.         case LOX:                        /* must be lox */
  693.             switch(cmd)
  694.             {
  695.             case 0:
  696.                 if (value == 27)        /* escape sequence */
  697.                 {
  698.                     state[vw] = ESCOUT;
  699.                     savstate[vw] = LOX;
  700.                 }
  701.                 else if (value < 27)    /* ignore */
  702.                 {
  703.                     break;
  704.                 }
  705.                 else
  706.                 {
  707.                     state[vw] = DONE;
  708.                     goagain = TRUE;
  709.                 }
  710.                 break;
  711.             case 2:
  712.                 vp->nlox = value;
  713.                 state[vw] = DONE;
  714.                 break;
  715.             }
  716.             break;
  717.     
  718.         case ENTERVEC:
  719.             if (c == 7) vp->mode = DRAW;
  720.             if (c < 32)
  721.             {
  722.                 state[vw] = DONE;
  723.                 goagain = TRUE;
  724.                 vp->mode = DONE;
  725.                 break;
  726.             }
  727.             state[vw] = HIY;
  728.             vp->mode = TEMPMOVE;
  729.             vp->modesave = DRAW;
  730.             goagain = TRUE;
  731.             break;
  732.         case RS:
  733.             switch (c)
  734.             {
  735.             case ' ':                /* pen up */
  736.                 vp->modesave = vp->mode;
  737.                 vp->mode = TEMPMOVE;
  738.                 break;
  739.             case 'P':                /* pen down */
  740.                 vp->mode = DRAW;
  741.                 break;
  742.             case 'D':                /* move up */
  743.                 vp->cury++;
  744.                 break;
  745.             case 'E':
  746.                 vp->cury++;
  747.                 vp->curx++;
  748.                 break;
  749.             case 'A':
  750.                 vp->curx++;
  751.                 break;
  752.             case 'I':
  753.                 vp->curx++;
  754.                 vp->cury--;
  755.                 break;
  756.             case 'H':
  757.                 vp->cury--;
  758.                 break;
  759.             case 'J':
  760.                 vp->curx--;
  761.                 vp->cury--;
  762.                 break;
  763.             case 'B':
  764.                 vp->curx--;
  765.                 break;
  766.             case 'F':
  767.                 vp->cury++;
  768.                 vp->curx--;
  769.                 break;
  770.             case 27:
  771.                 savstate[vw] = RS;
  772.                 state[vw] = ESCOUT;
  773.                 break;
  774.             default:
  775. /*                storexy(vw,vp->curx,vp->cury);*/
  776.                 state[vw] = CANCEL;
  777.                 goagain = TRUE;
  778.                 break;
  779.             }
  780.             if (vp->mode == DRAW)
  781.                 clipvec(vw,vp->curx,vp->cury,vp->curx,vp->cury);
  782.             break;
  783.         case CMD0: /* *->CMD0: get 1st letter of cmd */
  784.             switch(c)
  785.             {
  786.             case 29:                    /* GS, start draw */
  787.                 state[vw] = DONE;
  788.                 goagain = TRUE;
  789.                 break;
  790.             case '%':
  791.                 state[vw] = TERMSTAT;
  792.                 break;
  793.             case '8':
  794.                 fontnum(vw,0);
  795.                 state[vw] = DONE;
  796.                 break;
  797.             case '9':
  798.                 fontnum(vw,1);
  799.                 state[vw] = DONE;
  800.                 break;
  801.             case ':':
  802.                 fontnum(vw,2);
  803.                 state[vw] = DONE;
  804.                 break;
  805.             case ';':
  806.                 fontnum(vw,3);
  807.                 state[vw] = DONE;
  808.                 break;
  809.             case 12: /* form feed = clrscr */
  810.                 if (screens[findbyVS(vp->theVS)].tekclear) {
  811.                     VGpage(vw);
  812.                     VGclrstor(vw);
  813.                 }
  814.                 break;
  815.             case 'L':
  816.                 state[vw] = SOMEL;
  817.                 break;
  818.             case 'K':
  819.                 state[vw] = IGNORE;
  820.                 break;
  821.             case 'M':
  822.                 state[vw] = SOMEM;
  823.                 break;
  824.             case 'R':
  825.                 state[vw] = SOMER;
  826.                 break;
  827.             case 'T':
  828.                 state[vw] = SOMET;
  829.                 break;
  830.             case 26:
  831.                 (*RG[vp->RGdevice].gin)(vp->RGnum);
  832.                 TEKunstore(VGstore[vw]);
  833.                 TEKunstore(VGstore[vw]);
  834.                 break;
  835.             case 10:
  836.             case 13:
  837.             case 27:
  838.             case '~':
  839.                 savstate[vw] = DONE;
  840.                 state[vw] = ESCOUT;
  841.                 break;            /* completely ignore these after ESC */
  842.             default:
  843.                 state[vw] = DONE;
  844.             }
  845.             break;
  846.         case TERMSTAT:
  847.             switch(c)
  848.             {
  849.                 case '!':
  850.                     state[vw] = INTEGER;        /* Drop the next integer */
  851.                     savstate[vw] = DONE;
  852.                     break;
  853.             }
  854.             break;
  855.         case SOMER:
  856.             switch(c)
  857.             {
  858.                 case 'A':
  859.                     state[vw] = INTEGER;
  860.                     savstate[vw] = VIEWAT;
  861.                     break;
  862.                 default:
  863.                     state[vw] = DONE;
  864.             }
  865.             break;
  866.         case VIEWAT:
  867.             state[vw] = INTEGER;
  868.             savstate[vw] = VIEWAT2;
  869.             goagain = TRUE;
  870.             break;
  871.         case VIEWAT2:
  872.             vp->TEKBackground = vp->intin < 0 ? 0 : vp->intin > 7 ? 7 : vp->intin;
  873.             state[vw] = INTEGER;
  874.             savstate[vw] = DONE;
  875.             goagain = TRUE;
  876.             break;
  877.         case SOMET:                /* Got ESC T; now handle 3rd char. */
  878.             switch(c)
  879.             {
  880.             case 'C':            /* GCURSOR */
  881.                 vp->intin = 3;
  882.                 state[vw] = STARTDISC;
  883.                 break;
  884.             case 'D':
  885.                 vp->intin = 2;
  886.                 state[vw] = STARTDISC;
  887.                 break;
  888.             case 'F':            /* set dialog area color map */
  889.                 state[vw] = JUNKARRAY;
  890.                 break;
  891.             case 'G':            /* set surface color map */
  892.                 state[vw] = INTEGER;
  893.                 savstate[vw] = JUNKARRAY;
  894.                 break;
  895.             default:
  896.                 state[vw] = DONE;
  897.             }            
  898.             break;
  899.         case JUNKARRAY:            /* This character is the beginning of an integer
  900.                                     array to be discarded.  Get array size. */
  901.             savstate[vw] = STARTDISC;
  902.             state[vw] = INTEGER;
  903.             break;                    
  904.         case STARTDISC:            /* Begin discarding integers. */
  905.             vp->count = vp->intin + 1;
  906.             goagain = TRUE;
  907.             state[vw] = DISCARDING;
  908.             break;
  909.         case DISCARDING:
  910.             /* We are in the process of discarding an integer array. */
  911.             goagain = TRUE;
  912.             if (!(--(vp->count))) state[vw] = DONE;
  913.             else if (vp->count == 1)
  914.             {
  915.                 state[vw] = INTEGER;
  916.                 savstate[vw] = DONE;
  917.             }
  918.             else
  919.             {
  920.                 state[vw] = INTEGER;
  921.                 savstate[vw] = DISCARDING;
  922.             }
  923.             break;
  924.         case INTEGER:
  925.             if (c & 0x40)
  926.             {
  927.                 vp->intin = c & 0x3f;
  928.                 state[vw] = INTEGER1;
  929.             }
  930.             else
  931.             {
  932.                 vp->intin = c & 0x0f;
  933.                 if (!(c & 0x10)) vp->intin *= -1;
  934.                 state[vw] = savstate[vw];
  935.             }
  936.             break;
  937.         case INTEGER1:
  938.             if (c & 0x40)
  939.             {
  940.                 vp->intin = (vp->intin << 6) | (c & 0x3f);
  941.                 state[vw] = INTEGER2;
  942.             }
  943.             else
  944.             {
  945.                 vp->intin = (vp->intin << 4) | (c & 0x0f);
  946.                 if (!(c & 0x10)) vp->intin *= -1;
  947.                 state[vw] = savstate[vw];
  948.             }
  949.             break;
  950.         case INTEGER2:
  951.             vp->intin = (vp->intin << 4) | (c & 0x0f);
  952.             if (!(c & 0x10)) vp->intin *= -1;
  953.             state[vw] = savstate[vw];
  954.             break;
  955.         case IGNORE:            /* ignore next char; it's not supported */
  956.             state[vw] = DONE;
  957.             break;
  958.         case IGNORE2:            /* ignore next 2 chars */
  959.             state[vw] = IGNORE;
  960.             break;
  961.         case SOMEL:                /* now process 2nd letter */
  962.             switch(c)
  963.             {
  964.             case 'E':                    /* END PANEL 25jul90dsw */
  965.                 if (vp->TEKtype)
  966.                 {
  967.                     if (vp->TEKPanel)
  968.                     {
  969.                         if ((vp->current->x != vp->savx) ||
  970.                             (vp->current->y != vp->savy))
  971.                         {
  972.                             temppoint = (pointlist) NewPtr(sizeof(point));
  973.                             temppoint->x = vp->savx;
  974.                             temppoint->y = vp->savy;
  975.                             temppoint->next = (pointlist) NULL;
  976.                             vp->current->next = temppoint;
  977.                         }
  978.                         temppoint = vp->current = vp->TEKPanel;
  979.                         vp->savx = vp->curx = vp->current->x;
  980.                         vp->savy = vp->cury = vp->current->y;
  981.                         vp->current = vp->current->next;
  982.                         DisposPtr((Ptr) temppoint);
  983.                         PanelRgn = NewRgn();
  984.                         OpenRgn();
  985.                         while (vp->current)
  986.                         {
  987.                             clipvec(vw,vp->curx,vp->cury,
  988.                                     vp->current->x,vp->current->y);
  989.                             temppoint = vp->current;
  990.                             vp->curx = vp->current->x;
  991.                             vp->cury = vp->current->y;
  992.                             vp->current = vp->current->next;
  993.                             DisposPtr((Ptr) temppoint);
  994.                         }
  995.                         CloseRgn(PanelRgn);
  996.                         if (vp->TEKPattern <= 0)
  997.                             (*RG[vp->RGdevice].pencolor)(vp->RGnum,-vp->TEKPattern);
  998.                         PaintRgn(PanelRgn);
  999.                 /*        if (vp->TEKOutline) 
  1000.                             FrameRgn(PanelRgn); */
  1001.                         DisposeRgn(PanelRgn);
  1002.                         (*RG[vp->RGdevice].pencolor)(vp->RGnum,vp->pencolor);
  1003.                         vp->TEKPanel = (pointlist) NULL;
  1004.                         vp->curx = vp->savx;
  1005.                         vp->cury = vp->savy;
  1006.                     }
  1007.                 }
  1008.                 state[vw] = DONE;
  1009.                 break;
  1010.             case 'F':                    /* MOVE */
  1011.                 vp->modesave = vp->mode;
  1012.                 vp->mode = TEMPMOVE;
  1013.                 state[vw] = HIY;
  1014.                 break;
  1015.             case 'G':                    /* DRAW */
  1016.                 vp->modesave = vp->mode;
  1017.                 vp->mode = TEMPDRAW;
  1018.                 state[vw] = HIY;
  1019.                 break;
  1020.             case 'H':                    /* MARKER */
  1021.                 vp->modesave = vp->mode;
  1022.                 vp->mode = TEMPMARK;
  1023.                 state[vw] = HIY;
  1024.                 break;
  1025.             case 'I':                    /* DAINDEX 24jul90dsw*/
  1026.                 state[vw] = STARTDISC;
  1027.                 vp->intin = 3;
  1028.                 break;
  1029.             case 'L':
  1030.                 state[vw] = INTEGER;
  1031.                 savstate[vw] = DONE;
  1032.                 break;
  1033.             case 'P':                    /* BEGIN PANEL 17jul90dsw */
  1034.                 if (vp->TEKtype)        /* 4105 only */
  1035.                 {
  1036.                     state[vw] = HIY;
  1037.                     vp->mode = PANEL;
  1038.                 }
  1039.                 else
  1040.                     state[vw] = DONE;
  1041.                 break;
  1042.             case 'T':                    /* GTEXT 17jul90dsw */
  1043.                 if (vp->TEKtype)        /* 4105 only */
  1044.                 {
  1045.                     savstate[vw] = GTEXT;
  1046.                     state[vw] = INTEGER;
  1047.                 }
  1048.                 else
  1049.                     state[vw] = DONE;
  1050.                 break;
  1051.             default:
  1052.                 state[vw] = DONE;
  1053.             }
  1054.             break;
  1055.         case SOMEM:
  1056.             switch(c)
  1057.             {
  1058.             case 'C':                    /* set graphtext size */
  1059.                 savstate[vw] = GTSIZE0;
  1060.                 state[vw] = INTEGER;
  1061.                 break;
  1062.             case 'L':                    /* set line index */
  1063.                 savstate[vw] = COLORINT;
  1064.                 state[vw] = INTEGER;
  1065.                 break;
  1066.             case 'M':                    /* MARKERTYPE 17jul90dsw */
  1067.                 if (vp->TEKtype)
  1068.                 {
  1069.                     savstate[vw] = MARKER;
  1070.                     state[vw] = INTEGER;
  1071.                 }
  1072.                 else
  1073.                     state[vw] = DONE;
  1074.                 break;
  1075.             case 'N':                    /* GTPATH 17jul90dsw */
  1076.                 if (vp->TEKtype)
  1077.                 {
  1078.                     savstate[vw] = GTPATH;
  1079.                     state[vw] = INTEGER;
  1080.                 }
  1081.                 else
  1082.                     state[vw] = DONE;
  1083.                 break;
  1084.             case 'P':                    /* FillPattern 17jul90dsw */
  1085.                 if (vp->TEKtype)
  1086.                 {
  1087.                     savstate[vw] = FPATTERN;
  1088.                     state[vw] = INTEGER;
  1089.                 }
  1090.                 else
  1091.                     state[vw] = DONE;
  1092.                 break;
  1093.             case 'R':                    /* GTROT 17jul90dsw */
  1094.                 if (vp->TEKtype)
  1095.                 {
  1096.                     savstate[vw] = GTROT;
  1097.                     state[vw] = INTEGER;
  1098.                 }
  1099.                 else
  1100.                     state[vw] = DONE;
  1101.                 break;
  1102.             case 'T':                    /* GTINDEX 17jul90dsw */
  1103.                 if (vp->TEKtype)
  1104.                 {
  1105.                     savstate[vw] = GTINDEX;
  1106.                     state[vw] = INTEGER;
  1107.                 }
  1108.                 else
  1109.                     state[vw] = DONE;
  1110.                 break;
  1111.             case 'V':
  1112.                 if (vp->TEKtype)
  1113.                 {
  1114.                     state[vw] = INTEGER;
  1115.                     savstate[vw] = DONE;
  1116.                 }
  1117.                 else
  1118.                     state[vw] = DONE;
  1119.                 break;
  1120.             default:
  1121.                 state[vw] = DONE;
  1122.             }
  1123.             break;
  1124.         case COLORINT:                /* set line index; have integer */
  1125.             vp->pencolor = vp->intin;
  1126.             (*RG[vp->RGdevice].pencolor)(vp->RGnum,vp->intin);
  1127.             state[vw] = CANCEL;
  1128.             goagain = TRUE;            /* we ignored current char; now process it */
  1129.             break;
  1130.         case GTSIZE0:                /* discard the first integer; get the 2nd */
  1131.             state[vw] = INTEGER;    /* get the important middle integer */
  1132.             savstate[vw] = GTSIZE1;
  1133.             goagain = TRUE;
  1134.             break;
  1135.         case GTSIZE1:                /* integer is the height */
  1136.             if (vp->TEKtype)
  1137.             {
  1138.                 if (vp->intin < 88) vp->TEKSize = 1;
  1139.                 else if ((vp->intin > 87) && (vp->intin < 149)) vp->TEKSize = 2;
  1140.                 else if ((vp->intin > 148) && (vp->intin < 209)) vp->TEKSize = 3;
  1141.                 else if (vp->intin > 208) vp->TEKSize = vp->intin / 61;
  1142.                 VGwin[vw]->charx = (vp->TEKSize * 52);
  1143.                 VGwin[vw]->chary = (vp->TEKSize * 64);
  1144.             }
  1145.             else
  1146.             {
  1147.                 if (vp->intin < 88)
  1148.                     fontnum(vw,0);
  1149.                 else if (vp->intin < 149)
  1150.                     fontnum(vw,4);
  1151.                 else
  1152.                     fontnum(vw,5);
  1153.             }
  1154.             state[vw] = INTEGER;    /* discard last integer */
  1155.             savstate[vw] = DONE;
  1156.             goagain = TRUE;
  1157.             break;
  1158.         case GTEXT:                    /* TEK4105 GraphText output.  17jul90dsw */
  1159.             if (vp->intin > 0)
  1160.             {
  1161.                 drawc(vw,(short) c);    /* Draw the character */
  1162.                 vp->intin--;        /* One less character in the string... */
  1163.             }
  1164.             else
  1165.             {
  1166.                 goagain = TRUE;
  1167.                 state[vw] = DONE;
  1168.                 newcoord(vw);
  1169.             }
  1170.             break;
  1171.         case MARKER:                /* TEK4105 Set marker type.  17jul90dsw */
  1172.             vp->TEKMarker = vp->intin;
  1173.             if (vp->TEKMarker > 10) vp->TEKMarker = 10;
  1174.             if (vp->TEKMarker <  0) vp->TEKMarker = 0;
  1175.             state[vw] = DONE;
  1176.             goagain = TRUE;
  1177.             break;
  1178.         case GTPATH:
  1179.             vp->TEKPath = vp->intin;
  1180.             state[vw] = DONE;
  1181.             goagain = TRUE;
  1182.             break;
  1183.         case FPATTERN:
  1184.             vp->TEKPattern = (vp->intin <  -7) ?  -7 :
  1185.                              (vp->intin > 149) ? 149 : vp->intin;
  1186.             state[vw] = DONE;
  1187.             goagain = TRUE;
  1188.             break;
  1189.         case GTROT:
  1190.             vp->TEKRot = vp->intin;
  1191.             state[vw] = INTEGER;
  1192.             savstate[vw] = GTROT1;
  1193.             goagain = TRUE;
  1194.             break;
  1195.         case GTROT1:
  1196.             vp->TEKRot = (vp->TEKRot) << (vp->intin);
  1197.             vp->TEKRot = ((vp->TEKRot + 45) / 90) * 90;
  1198.             state[vw] = DONE;
  1199.             goagain = TRUE;
  1200.             break;
  1201.         case GTINDEX:
  1202.             vp->TEKIndex = (vp->intin < 0) ? 0 : (vp->intin > 7) ? 7 : vp->intin;
  1203.             state[vw] = DONE;
  1204.             goagain = TRUE;
  1205.             break;
  1206.         case PANEL:
  1207.             vp->TEKOutline = (vp->intin == 0) ? 0 : 1;
  1208.             temppoint = (pointlist) NewPtr(sizeof(point));
  1209.             if (vp->TEKPanel)
  1210.             {
  1211.                 if ((vp->current->x != vp->savx) && (vp->current->y != vp->savy))
  1212.                 {
  1213.                     temppoint->x = vp->savx;
  1214.                     temppoint->y = vp->savy;
  1215.                     vp->current->next = temppoint;
  1216.                     vp->current = temppoint;
  1217.                     temppoint = (pointlist) NewPtr(sizeof(point));
  1218.                 }
  1219.                 vp->current->next = temppoint;
  1220.             }
  1221.             else vp->TEKPanel = temppoint;
  1222.             vp->current = temppoint;
  1223.             vp->current->x = vp->savx = joinup(vp->nhix,vp->nlox,vp->nex);
  1224.             vp->current->y = vp->savy = joinup(vp->nhiy,vp->nloy,vp->ney);
  1225.             vp->current->next = (pointlist) NULL;
  1226.             state[vw] = INTEGER;
  1227.             savstate[vw] = PANEL;
  1228.             vp->mode = DONE;
  1229.             newcoord(vw);
  1230.             state[vw] = DONE;
  1231.             goagain = TRUE;
  1232.             break;
  1233.         case DONE:                    /* ready for anything */
  1234.             switch(c)
  1235.             {
  1236.             case 31:                /* US - enter ALPHA mode */
  1237.                 vp->mode = ALPHA; 
  1238.                 state[vw] = CANCEL;
  1239.                 break;
  1240.             case 30:
  1241.                 state[vw] = RS;
  1242.                 break;
  1243.             case 28:
  1244.                     vp->mode = MARK;
  1245.                     state[vw] = HIY;
  1246.                 break;
  1247.             case 29:                /* GS - enter VECTOR mode */
  1248.                 state[vw] = ENTERVEC;
  1249.                 break;
  1250.             case 27:
  1251.                 state[vw] = CMD0;
  1252.                 break;
  1253.             default:
  1254.                 if (vp->mode == ALPHA)
  1255.                 {
  1256.                     state[vw] = DONE;
  1257.                     if (! vp->TEKtype)
  1258.                         drawc(vw,(short) c);
  1259.                     else
  1260.                     {
  1261.                         VSwrite(vp->theVS,&c,1);
  1262.                         TEKunstore(VGstore[vw]);
  1263.                     }
  1264.                     return;
  1265.                 }
  1266.                 else if ((vp->mode == DRAW) && cmd)
  1267.                 {
  1268.                     state[vw] = HIY;
  1269.                     goagain = TRUE;
  1270.                 }
  1271.                 else if ((vp->mode == MARK) && cmd)
  1272.                 {
  1273.                     state[vw] = HIY;
  1274.                     goagain = TRUE;
  1275.                 }
  1276.                 else if ((vp->mode == DRAW) && ((c == 13) || (c == 10)))
  1277.                 {
  1278.                     /* break drawing mode on CRLF */
  1279.                     vp->mode = ALPHA; 
  1280.                     state[vw] = CANCEL;
  1281.                 }
  1282.                 else
  1283.                 {
  1284.                     state[vw] = DONE;            /* do nothing */
  1285.                     return;
  1286.                 }
  1287.             }
  1288.         }
  1289.     
  1290.         if (state[vw] == DONE)
  1291.         {
  1292.             if (vp->mode == PANEL)
  1293.             {
  1294.                 vp->mode = DONE;
  1295.                 state[vw] = INTEGER;
  1296.                 savstate[vw] = PANEL;
  1297.             }
  1298.             else if ((vp->TEKPanel) && ((vp->mode == DRAW) || (vp->mode == TEMPDRAW)
  1299.                     || (vp->mode == MARK) || (vp->mode == TEMPMARK) ||
  1300.                         (vp->mode == TEMPMOVE)))
  1301.             {
  1302.                 temppoint = (pointlist) NewPtr(sizeof(point));
  1303.                 vp->current->next = temppoint;
  1304.                 vp->current = temppoint;
  1305.                 vp->current->x = joinup(vp->nhix,vp->nlox,vp->nex);
  1306.                 vp->current->y = joinup(vp->nhiy,vp->nloy,vp->ney);
  1307.                 vp->current->next = (pointlist) NULL;
  1308.                 if ((vp->mode == TEMPDRAW) || (vp->mode == TEMPMOVE) ||
  1309.                     (vp->mode == TEMPMARK))
  1310.                     vp->mode = vp->modesave;
  1311.                 newcoord(vw);
  1312.             }
  1313.             else if (vp->mode == TEMPMOVE)
  1314.             {
  1315.                 vp->mode = vp->modesave;
  1316.                 newcoord(vw);
  1317.             }
  1318.             else if ((vp->mode == DRAW) || (vp->mode == TEMPDRAW))
  1319.             {
  1320.                 clipvec(vw,vp->curx,vp->cury,
  1321.                     joinup(vp->nhix,vp->nlox,vp->nex),
  1322.                     joinup(vp->nhiy,vp->nloy,vp->ney));
  1323.                 newcoord(vw);
  1324.                 if (vp->mode == TEMPDRAW) vp->mode = vp->modesave;
  1325.             }
  1326.             else if ((vp->mode == MARK) || (vp->mode == TEMPMARK))
  1327.             {
  1328.                 newcoord(vw);
  1329.                 if (vp->TEKtype) drawc(vw,127 + vp->TEKMarker);
  1330.                 newcoord(vw);
  1331.                 if (vp->mode == TEMPMARK) vp->mode = vp->modesave;
  1332.             }
  1333.         }
  1334.  
  1335.         if (state[vw] == CANCEL) state[vw] = DONE;
  1336.     } while (goagain);
  1337.     return;
  1338. }
  1339.  
  1340. /*  Clear screen and have a few other effects:
  1341.  *    - Return graphics to home position (0,3071)
  1342.  *    - Switch to alpha mode
  1343.  *    This is a standard Tek command; don't look at me.
  1344.  */
  1345. void VGpage(short vw)
  1346. {
  1347.     if (VGcheck(vw)) {
  1348.         return;
  1349.         }
  1350.  
  1351.     if (VGwin[vw]->TEKtype)
  1352.         (*RG[VGwin[vw]->RGdevice].pencolor)(VGwin[vw]->RGnum,VGwin[vw]->TEKBackground);
  1353.     else
  1354.         (*RG[VGwin[vw]->RGdevice].pencolor)(VGwin[vw]->RGnum,0);
  1355.     (*RG[VGwin[vw]->RGdevice].clrscr)(VGwin[vw]->RGnum);
  1356.     (*RG[VGwin[vw]->RGdevice].pencolor)(VGwin[vw]->RGnum,1);
  1357.     VGwin[vw]->mode = ALPHA;
  1358.     state[vw] = DONE;
  1359.     VGwin[vw]->textcol = 0;
  1360.     fontnum(vw,0);
  1361.     storexy(vw,0,3071);
  1362. }
  1363.  
  1364. /*    Redraw window 'vw' in pieces to window 'dest'.
  1365.  *    Must call this function repeatedly to draw whole image.
  1366.  *    Only draws part of the image at a time, to yield CPU power.
  1367.  *    Returns 0 if needs to be called more, or 1 if the image
  1368.  *    is complete.  Another call would result in the redraw beginning again.
  1369.  *    User should clear screen before beginning redraw.
  1370.  */
  1371. short VGpred(short vw, short dest)
  1372. {
  1373.     short        data;
  1374.     TEKSTOREP    st;
  1375.     short        count = 0;
  1376.     
  1377.     if (VGcheck(vw)) {
  1378.         return -1;
  1379.         }
  1380.  
  1381.     st = VGstore[vw];
  1382.     
  1383.     if (drawing[vw])        /* wasn't redrawing */
  1384.     {
  1385.         topTEKstore(VGstore[vw]);
  1386.         drawing[vw] = 0;    /* redraw incomplete */
  1387.     }
  1388.  
  1389.     while (++count < PREDCOUNT && ((data = nextTEKitem(st)) != -1))
  1390.         VGdraw(dest,data);
  1391.  
  1392.     if (data == -1) drawing[vw] = 1;     /* redraw complete */
  1393.     return(drawing[vw]);
  1394. }
  1395.  
  1396. /*    Abort VGpred redrawing of specified window.
  1397.     Must call this routine if you decide not to complete the redraw. */
  1398. void VGstopred(short vw)
  1399. {
  1400.     if (VGcheck(vw)) {
  1401.         return;
  1402.         }
  1403.  
  1404.     drawing[vw] = 1;
  1405. }
  1406.  
  1407. /*    Redraw the contents of window 'vw' to window 'dest'.
  1408.  *    Does not yield CPU until done.
  1409.  *    User should clear the screen before calling this, to avoid 
  1410.  *    a messy display. */
  1411. void VGredraw(short vw, short dest)
  1412. {
  1413.     short    data;
  1414.  
  1415.     if (VGcheck(vw)) {
  1416.         return;
  1417.         }
  1418.  
  1419.     topTEKstore(VGstore[vw]);
  1420.     while ((data = nextTEKitem(VGstore[vw])) != -1) VGdraw(dest,data);
  1421. }
  1422.  
  1423. /*    Send interesting information about the virtual window down to
  1424.  *    its RG, so that the RG can make VG calls and display zoom values
  1425.  */
  1426. void    VGgiveinfo(short vw)
  1427. {
  1428.     if (VGcheck(vw)) {
  1429.         return;
  1430.         }
  1431.  
  1432.     (*RG[VGwin[vw]->RGdevice].info)(VGwin[vw]->RGnum,
  1433.         vw,
  1434.         VGwin[vw]->winbot,
  1435.         VGwin[vw]->winleft,
  1436.         VGwin[vw]->wintop,
  1437.         VGwin[vw]->winright);
  1438. }
  1439.  
  1440. /*    Set new borders for zoom/pan region.
  1441.  *    x0,y0 is lower left; x1,y1 is upper right.
  1442.  *    User should redraw after calling this.
  1443.  */
  1444. void    VGzoom(short vw, short x0, short y0, short x1, short y1)
  1445. {
  1446.     if (VGcheck(vw)) {
  1447.         return;
  1448.         }
  1449.  
  1450.     VGwin[vw]->winbot = y0;
  1451.     VGwin[vw]->winleft = x0;
  1452.     VGwin[vw]->wintop = y1;
  1453.     VGwin[vw]->winright = x1;
  1454.     VGwin[vw]->wintall = y1 - y0 + 1;
  1455.     VGwin[vw]->winwide = x1 - x0 + 1;
  1456.     VGgiveinfo(vw);
  1457. }
  1458.  
  1459. void    VGwhatzoom(short vw, short *px0, short *py0, short *px1, short *py1)
  1460. {
  1461.     if (VGcheck(vw)) {
  1462.         return;
  1463.         }
  1464.  
  1465.     *py0 = VGwin[vw]->winbot;
  1466.     *px0 = VGwin[vw]->winleft;
  1467.     *py1 = VGwin[vw]->wintop;
  1468.     *px1 = VGwin[vw]->winright;
  1469. }
  1470.  
  1471. /*    Set zoom/pan borders for window 'dest' equal to those for window 'src'.
  1472.  *    User should redraw window 'dest' after calling this.
  1473.  */
  1474. void    VGzcpy(short src, short dest)
  1475. {
  1476.     VGzoom(dest,VGwin[src]->winleft, VGwin[src]->winbot,
  1477.     VGwin[src]->winright, VGwin[src]->wintop);
  1478. }
  1479.  
  1480. /*    Close virtual window.
  1481. /*    Draw the data pointed to by 'data' of length 'count'
  1482.  *    on window vw, and add it to the store for that window.
  1483.  *    This is THE way for user program to pass Tektronix data.
  1484.  */
  1485. short    VGwrite(short vw, char *data, short count)
  1486. {
  1487.     char *c = data;
  1488.     char *end = &(data[count]);
  1489.     char storeit;
  1490.  
  1491.     if (VGcheck(vw)) {
  1492.         return -1;
  1493.         }
  1494.  
  1495.     storeit = storing[vw];
  1496.     
  1497.     while (c != end)
  1498.     {
  1499.         if (*c == 24)                /* ASC CAN character */
  1500.             return(c-data+1);
  1501.         if (storeit) addTEKstore(VGstore[vw],*c);
  1502.         VGdraw(vw,*c++);
  1503.  
  1504.     }
  1505.     return(count);
  1506. }
  1507.  
  1508. /*    Return a pointer to a human-readable string
  1509.  *    which describes the specified real device
  1510.  */
  1511. char *    VGrgname(short rgdev)
  1512. {
  1513.     return(*RG[rgdev].devname)();
  1514. }
  1515.  
  1516. /*    Put the specified real device into text mode */
  1517. void    VGtmode(short rgdev)
  1518. {
  1519.     (*RG[rgdev].tmode)();
  1520. }
  1521.  
  1522. /*    Translate data for output as GIN report.
  1523.  *
  1524.  *    User indicates VW number and x,y coordinates of the GIN cursor.
  1525.  *    Coordinate space is 0-4095, 0-4095 with 0,0 at the bottom left of
  1526.  *    the real window and 4095,4095 at the upper right of the real window.
  1527.  *    'c' is the character to be returned as the keypress.
  1528.  *    'a' is a pointer to an array of 5 characters.  The 5 chars must
  1529.  *    be transmitted by the user to the remote host as the GIN report. */
  1530. void VGgindata( short vw,
  1531.     unsigned short x,        /* NCSA: SB - UNSIGNED data */
  1532.     unsigned short y,        /* NCSA: SB - "          "  */
  1533.     char c, char *a)
  1534. {
  1535.     long    x2,y2;
  1536.     
  1537.     if (VGcheck(vw)) {
  1538.         return;
  1539.         }
  1540.  
  1541.     x2 = ((x * VGwin[vw]->winwide) / INXMAX + VGwin[vw]->winleft) >> 2;
  1542.     y2 = ((y * VGwin[vw]->wintall) / INYMAX + VGwin[vw]->winbot) >> 2;
  1543.  
  1544.     a[0] = c;
  1545.     a[1] = 0x20 | ((x2 & 0x03E0) >> 5);
  1546.     a[2] = 0x20 | (x2 & 0x001F);
  1547.     a[3] = 0x20 | ((y2 & 0x03E0) >> 5);
  1548.     a[4] = 0x20 | (y2 & 0x001F);
  1549. }
  1550.